package taxi_map.model;

import java.io.IOException;
import java.math.BigDecimal;
import java.sql.SQLException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.HashMap;

import javax.servlet.http.HttpSession;

import member.model.MemberDAO;
import taxi_map.controller.WaitingUser;
import to.HistoryTO;
import to.MemberTO;
import to.WaitingDriverTO;
import driver.model.DriverDAO;

public class TaxiMapService {
	/*
	 * 현재 기다리고 있는 택시들의 번호들과 thread 이름을 가지고 있는 static hashmap
	 */
	DriverDAO driverDAO;
	MemberDAO memberDAO;
	TaxiMapDAO taxiMapDAO;
	String phoneNumber;
	static HashMap<String, WaitingUser> taxiMapServiceHashMap = new HashMap<String,WaitingUser>();
	static HashMap<String, WaitingUser> userMapServiceHashMap = new HashMap<String,WaitingUser>();
	static HashMap<String, String> userDriverNumber = new HashMap<String,String>();
	static HashMap<String, String> driverUserNumber = new HashMap<String,String>();
	
	public TaxiMapService(MemberDAO memberDAO, TaxiMapDAO taxiMapDAO){
		this.memberDAO = memberDAO;
		this.taxiMapDAO = taxiMapDAO;
	}
	
	public WaitingUser clientCall(HttpSession session, String DriverNumber, WaitingUser newWaiter, HashMap<String,BigDecimal> condition) throws IOException{
		WaitingDriverTO wto = taxiMapDAO.findNearestWaitingDriver(condition);
		WaitingUser result = null;
		if(wto != null){
			if(getDistance(wto, condition).intValue() < 10){
				taxiMapDAO.deleteWaitingDriver(wto.getPhoneNumber());
				if(DriverNumber != null){
					newWaiter = userMapServiceHashMap.get(DriverNumber);
					userMapServiceHashMap.remove(DriverNumber);
					String clientNumber = driverUserNumber.get(DriverNumber);
					userDriverNumber.remove(clientNumber);
					userDriverNumber.put(clientNumber, wto.getPhoneNumber());
					driverUserNumber.put(wto.getPhoneNumber(),clientNumber);
					driverUserNumber.remove(DriverNumber);
				}else{
					userDriverNumber.put(((MemberTO) session.getAttribute("login_info")).getPhone(), wto.getPhoneNumber());
					driverUserNumber.put(wto.getPhoneNumber(),((MemberTO) session.getAttribute("login_info")).getPhone());
				}
				userMapServiceHashMap.put(wto.getPhoneNumber(), newWaiter);
				result = taxiMapServiceHashMap.get(wto.getPhoneNumber());
				taxiMapServiceHashMap.remove(wto.getPhoneNumber());
			}
		}
		return result;
	}
	
	public void registerHistory(HttpSession session) throws SQLException{
		String userNumber = ((MemberTO) session.getAttribute("login_info")).getPhone();
		String driverNumber = userDriverNumber.get(userNumber);
		userDriverNumber.remove(userNumber);
		driverUserNumber.remove(driverNumber);
		DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
		Calendar calendar = Calendar.getInstance();
		HistoryTO newHistory = new HistoryTO(0, userNumber, driverNumber, dateFormat.format(calendar.getTime()), null, null);
		session.setAttribute("newHistory", newHistory);
	}
	
	public BigDecimal getDistance(WaitingDriverTO wto, HashMap<String,BigDecimal> condition){
		BigDecimal lat2 = wto.getLatitude();
		BigDecimal lon2 = wto.getLongitude();
		BigDecimal lat1 = (BigDecimal) condition.get("latitude");
		BigDecimal lon1 = (BigDecimal) condition.get("longitude");
		BigDecimal R = new BigDecimal(6371); // km
		BigDecimal dLat = new BigDecimal(Math.toRadians(lat2.subtract(lat1).doubleValue()));
		BigDecimal dLon = new BigDecimal(Math.toRadians(lon2.subtract(lon1).doubleValue()));
		Math.toRadians(lat1.doubleValue());
		Math.toRadians(lat2.doubleValue());
		Double a = 	Math.sin(dLat.divide(new BigDecimal(2)).doubleValue()) * Math.sin(dLat.divide(new BigDecimal(2)).doubleValue()) +
		        	Math.sin(dLon.divide(new BigDecimal(2)).doubleValue()) * Math.sin(dLon.divide(new BigDecimal(2)).doubleValue()) *
		        	Math.cos(lat1.doubleValue()) * Math.cos(lat2.doubleValue()); 
		Double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); 
		return R.multiply(new BigDecimal(c));
	}
	
	public WaitingUser respondCall(String DriverNumber){
		WaitingUser result = null;
		result = userMapServiceHashMap.get(DriverNumber);
		userMapServiceHashMap.remove(DriverNumber);
		return result;
	}
	
	public void registerDriverWait(WaitingDriverTO wto, WaitingUser newWaiter) throws IOException, InterruptedException{
		taxiMapDAO.insertWaitingDriver(wto);
		taxiMapServiceHashMap.put(wto.getPhoneNumber().trim(), newWaiter);
	}
}